import java.util.ArrayList;
import java.util.Iterator;


public class SuperDuperTag 
{	
	static CategoryAnalyst analyst = new CategoryAnalyst();
	static ArrayList<String> slashLibrary = new ArrayList<String>();	
	int width;
	//String raw;
	//String rawMinusSemantics;
	ArrayList<SuperDuperTag> args;
	ArrayList<String> slashes;
	ArrayList<SuperDuperTag> bag;
	ArrayList<String> bagOSlashes;
	int indexOfStringBaseInt;
	String stringBaseWithSemantics;
	String stringBaseMinusSemantics;
	int index;
	
	
	//constructor
	public SuperDuperTag(String input)
	{
		String raw;
		String rawMinusSemantics;
		bag = new ArrayList<SuperDuperTag>();
		bagOSlashes = new ArrayList<String>();
		slashes = new ArrayList<String>();
		args = new ArrayList<SuperDuperTag>();
		slashLibrary.add("/");
		slashLibrary.add("\\");
		slashLibrary.add("/*");
		slashLibrary.add("\\*");
		
		if(input.startsWith("(") && input.endsWith(")"))
		{
			input = input.substring(1,input.length()-1);
		}
		
		raw = input;
		rawMinusSemantics = analyst.cleanSupertag(raw);
		
		StevesSupertagParser stparser = new StevesSupertagParser(slashLibrary);
		ArrayList<String> partsMinusSemantics = stparser.parseSupertag(rawMinusSemantics);
		ArrayList<String> partsWithSemantics = stparser.parseSupertag(raw);
		//System.out.println(parts);
		stringBaseMinusSemantics = partsMinusSemantics.get(0);
		stringBaseWithSemantics = partsWithSemantics.get(0);
		String indexOfStringBase = stringBaseWithSemantics.substring(stringBaseWithSemantics.indexOf("_") + 1,stringBaseWithSemantics.length());
		indexOfStringBaseInt = Integer.parseInt(indexOfStringBase);
		if(partsMinusSemantics.size() > 1)
		{
			Iterator<String> i = partsWithSemantics.iterator();
			i.next();
			while(i.hasNext())
			{
				String temp = i.next();
				String slash = startsWithSlash(temp);
				if(slash == null)
				{
					System.err.println("SuperDuperTag: error.");
				}

				temp = temp.substring(slash.length(), temp.length());
				slashes.add(slash);
				args.add(new SuperDuperTag(temp));
			}	
			index = -1;
		}
		else
		{
			index = Integer.parseInt(indexOfStringBase);
		}
	
		width = 1;

		for(SuperDuperTag spotlight : args)
		{
			width += spotlight.getWidth();
		}

	}
	
//	copy constructor
	public SuperDuperTag(SuperDuperTag input)
	{
		slashLibrary = new ArrayList<String>(input.getSlashLib());
		//raw = input.getRaw();
		//rawMinusSemantics = input.getRawMinusSemantics();
		args = new ArrayList<SuperDuperTag>(input.getArgs());
		slashes = new ArrayList<String>(input.getSlashes());
		bagOSlashes = new ArrayList<String>(input.getBagOSlashes());
		bag = new ArrayList<SuperDuperTag>(input.getBag());
		width = input.getWidth();
		stringBaseWithSemantics = input.getBase();
		stringBaseMinusSemantics = input.getBaseMinusSemantics();
		indexOfStringBaseInt = input.getIndexOfStringBase();
	//	this.index = input.getHeadIndex();
	}
	
	
	/*******************
	 * Important Functions
	 *******************/
	
	public void addToArgsAtBegining(ArrayList<SuperDuperTag> args, ArrayList<String> slashes)
	{
		ArrayList<SuperDuperTag> temp1 = new ArrayList<SuperDuperTag>();
		temp1.addAll(args);
		temp1.addAll(this.args);
		
		ArrayList<String> temp2 = new ArrayList<String>();
		temp2.addAll(slashes);
		temp2.addAll(this.slashes);
		
		this.args = temp1;
		this.slashes = temp2;
		
	}
	
	public void addToArgs(ArrayList<SuperDuperTag> args, ArrayList<String> slashes)
	{
		this.args.addAll(args);
		this.slashes.addAll(slashes);
	}
	
	public int getIndexOfStringBase()
	{
		return indexOfStringBaseInt;
	}
	
	public int getLeftmostIndex()
	{
		return indexOfStringBaseInt;
	}
	
	public String getLeftmostSlash()
	{
		if(slashes.isEmpty())
			return null;
		else return slashes.get(0);
	}
	
	public int getSemIndex()
	{
		return index;
	}
	
	public SuperDuperTag getRightmostArg()
	{
		if(args.size() == 0)
			return null;
		return args.get(args.size()-1);
	}
	
	public String getRightmostSlash()
	{
		if(slashes.size() == 0)
			return "NOSLASH";
		else return slashes.get(slashes.size()-1);
	}
	
	public void setBase(String temp)
	{
		stringBaseWithSemantics = temp;
		stringBaseMinusSemantics = analyst.cleanSupertag(temp);
	}
	
	public void consumeOne()
	{
		bag.add(args.remove(args.size()-1));
		bagOSlashes.add(slashes.remove(slashes.size()-1));
	}
	
	public String startsWithSlash(String input)
	{
		//Iterator<String> i = slashLibrary.iterator();
		for(String slash : slashLibrary)
		{
			//String slash = i.next();
			if(input.startsWith(slash))
				return slash;
		}
		return null;
	}
	
	public String toStringReadable()
	{
		String result = "(" + stringBaseWithSemantics;
		for(int a = 0; a < args.size(); a++)
		{
			result += " " + slashes.get(a) + " " + args.get(a).toStringReadable();
		}
		return result + ")";
	}
	
	public String toString()
	{
		String result = stringBaseWithSemantics;
		for(int a = 0; a < args.size(); a++)
		{
			result += " " + slashes.get(a) + " " + args.get(a);
		}
		return result;
	}
	
	public String toStringForComp()
	{
		String result = stringBaseMinusSemantics;
		for(int a = 0; a < args.size(); a++)
		{
			result += slashes.get(a) + args.get(a).toStringForComp();
		}
		return result;
	}
	
	public String toStringWithBag()
	{
		String result = "Tag: " + stringBaseWithSemantics;
		for(int a = 0; a < args.size(); a++)
		{
			result += " " + slashes.get(a) + " " + args.get(a);
		}
		result += "\nBag: " + bag.toString();
		return result;
	}
	
	/*public String getRawMinusSemantics()
	{
		return rawMinusSemantics;
	}*/
	
	public boolean equals(Object o)
	{
		if(this == o)
			return true;
		else if(this.getClass() != o.getClass())
			return false;
		else
		{
		
			SuperDuperTag s = (SuperDuperTag) o;
			//System.out.println("Comparing:");
			return(args.equals(s.getArgs()) && stringBaseMinusSemantics.equals(s.getBaseMinusSemantics()) && slashes.equals(s.getSlashes()));
		}
	}
	
	/**************
	 * Accessors
	 **************/
	
	public int getWidth()
	{
		return width;
	}
	
	public ArrayList<String> getBagOSlashes()
	{
		return bagOSlashes;
	}
	
	public String getBaseMinusSemantics()
	{
		return stringBaseMinusSemantics;
	}
	public String getBase()
	{
		return stringBaseWithSemantics;
	}
	
	public ArrayList<SuperDuperTag> getBag()
	{
		return bag;
	}
	
	public ArrayList<String> getSlashes()
	{
		return slashes;
	}
	
	public ArrayList<SuperDuperTag> getArgs()
	{
		return args;
	} 
	
	/*public String getRaw()
	{
		return raw;
	}*/
	
	public ArrayList<String> getSlashLib()
	{
		return slashLibrary;
	}
	
	public int getNumOfArgs()
	{
		return args.size();
	}
	
	public int hashCode()
	{
		return 31 * args.hashCode() + slashes.hashCode() + stringBaseWithSemantics.hashCode();
	}
	
}
